package com.jiashihui.schema_lgorithm.java.basics;

/**
 * @author jiashihui
 * @describe: final
 * @date 2019/03/25
 *
 * final关键字可以用来修饰类、方法和变量（包括成员变量和局部变量）
 * 1.修饰类
 * 当用final修饰一个类时，表明这个类不能被继承。也就是说，如果一个类你永远不会让他被继承，就可以用final进行修饰。
 * final类中的成员变量可以根据需要设为final，但是要注意final类中的所有成员方法都会被隐式地指定为final方法。
 * 2.修饰方法
 * 使用final方法的原因有两个。第一个原因是把方法锁定，以防任何继承类修改它的含义（父类的final方法是不能被子类所覆盖的）；第二个原因是效率。
 * 因为重写的前提是子类可以从父类中继承此方法，如果父类中final修饰的方法同时访问控制权限为private，将会导致子类中不能直接继承到此方法，因此，此时可以在子类中定义相同的方法名和参数，此时不再产生重写与final的矛盾，而是在子类中重新定义了新的方法。
 * （注：类的private方法会隐式地被指定为final方法。）
 * 3、修饰变量
 * final成员变量表示常量，只能被赋值一次，赋值后值不再改变。
 * (1)当final修饰一个基本数据类型时，表示该基本数据类型的值一旦在初始化后便不能发生变化；
 * (2)如果final修饰一个引用类型时，则在对其初始化之后便不能再让其指向其他对象了，但该引用所指向的对象的内容是可以发生变化的。
 * 初始化：
 * final修饰一个成员变量（属性），必须要显示初始化。这里有两种初始化方式，一种是在变量声明的时候初始化；
 * 第二种方法是在声明变量的时候不赋初值，但是要在这个变量所在的类的所有的构造函数中对这个变量赋初值。
 * 当函数的参数类型声明为final时，说明该参数是只读型的。即你可以读取使用该参数，但是无法改变该参数的值。
 *
 *
 */
public class FinalTest extends A {

    public FinalTest(){
        System.out.println("cccccccc");
    }

    static {
        System.out.println("dddddddd");
    }

    public static void main(String[] args){
        FinalTest testFinal = new FinalTest();
        StringBuffer buffer = new StringBuffer("hello");
        testFinal.changeValue(buffer);
        System.out.println(buffer);

    }

    public void changeValue(final StringBuffer buffer){
        // buffer重新指向另一个对象
        // buffer = new StringBuffer("hi");
        buffer.append("world");
        System.out.println(buffer);
    }

    private final int aa = 10;

    public void getName() {
        // aa = 20;
        System.out.println(aa);

    }
}

class A {

    public A(){
        System.out.println("aaaaaa");
    }

    static {
        System.out.println("bbbbbbbb");
    }

    /**
     * 因为private修饰，子类中不能继承到此方法，因此，子类中的getName方法是重新定义的、
     * 属于子类本身的方法，编译正常
     */
    private final void getName() {

    }

    // 因为pblic修饰，子类可以继承到此方法，导致重写了父类的final方法，编译出错
//    public final void getName() {
//
//    }
}
